package com.xlhl.init.common;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.function.Function;

/**
 * 自动实现 常用的 entity -> vo 实现方式
 * 默认使用的 VO 的构造函数 构造函数的参数为 Entity
 * <P>例：</P>
 * <p>
 * public VO(Entity entity) {}
 * </p>
 *
 * @param <Entity> Java 实体类
 * @param <VO>     Java VO 类
 * @author xlhl
 */
public interface EntityToVoService<Entity extends Serializable, VO extends Serializable> {

    /**
     * Page<Entity> -> Page<VO>
     *
     * @param page
     * @return
     */
    default Page<VO> pageToVoPage(Page<Entity> page) {
        return pageToVoPage(page, this::objToVo);
    }

    /**
     * Page<Entity> -> Page<VO>
     *
     * @param page
     * @param function 自定义转化 Entity -> VO
     * @return
     */
    default Page<VO> pageToVoPage(Page<Entity> page, Function<Entity, VO> function) {
        Page<VO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(listToVoList(page.getRecords(), function));

        return voPage;
    }

    /**
     * List<Entity> -> List<VO>
     *
     * @param list
     * @return
     */
    default List<VO> listToVoList(List<Entity> list) {
        return listToVoList(list, this::objToVo);
    }

    /**
     * List<Entity> -> List<VO>
     *
     * @param list
     * @param function 自定义转化 Entity -> VO
     * @return
     */
    default List<VO> listToVoList(List<Entity> list, Function<Entity, VO> function) {
        return list.stream().map(function).toList();
    }

    /**
     * Entity -> VO
     *
     * @param entity 实体对象
     * @return VO对象
     */
    default VO objToVo(Entity entity) {
        if (entity == null) {
            return null;
        }

        try {
            // 获取VO类的构造方法
            Constructor<VO> constructor = getVoClass().getConstructor(entity.getClass());
            // 使用构造方法创建VO实例
            return constructor.newInstance(entity);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("VO类缺少以实体类为参数的构造函数", e);
        } catch (Exception e) {
            throw new RuntimeException("创建VO对象失败", e);
        }
    }

    /**
     * 获取VO类的Class对象
     * <p>
     * 需要子类实现或通过其他方式确定VO类
     * <p>
     * 简单的 Entity -> VO 只需要返回 VO 的 class 对象即可
     * </p>
     *
     * @return VO 类型的 Class 对象
     */
    Class<VO> getVoClass();
}
